// Kony


#include "Actor/BaseProjectile.h"

#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"
#include "Components/SphereComponent.h"
#include "GASC_HuanLing/GASC_HuanLing.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Kismet/GameplayStatics.h"
#include "NiagaraFunctionLibrary.h"
#include "AbilitySystem/BaseAbilitySystemLibrary.h"
#include "Components/AudioComponent.h"
#include "TimerManager.h"

ABaseProjectile::ABaseProjectile()
{
 	PrimaryActorTick.bCanEverTick = false;
	bReplicates = true; //允许该Actor在服务器和客户端之间同步
	Sphere = CreateDefaultSubobject<USphereComponent>("Sphere");
	// SetRootComponent(Sphere);
	Sphere->SetupAttachment(GetRootComponent());
	//设置碰撞类型
	Sphere->SetCollisionObjectType(ECC_Projectile);
	Sphere->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
	//碰撞忽略所有通道
	Sphere->SetCollisionResponseToAllChannels(ECR_Ignore);
	Sphere->SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Overlap);
	Sphere->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Overlap);
	Sphere->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);

	//创建球体移动组件
	ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>("ProjectileMovement");
	ProjectileMovement->InitialSpeed=550.f; //初始速度
	ProjectileMovement->MaxSpeed=550.f; //最大速度
	ProjectileMovement->ProjectileGravityScale=0.f; //重力影响 0为无重力影响
}
void ABaseProjectile::BeginPlay()
{
	Super::BeginPlay();
	//设置生命周期
	SetLifeSpan(LifeTime);
	//设置客户端复制移动组件 用于网络同步
	SetReplicateMovement(true);
	//把球体绑定到球体碰撞重叠事件
	Sphere->OnComponentBeginOverlap.AddDynamic(this, &ABaseProjectile::OnSphereOverlap);
	//生成持续声音 附加到根组件，赋值到变量
	LoopingSoundComponent = UGameplayStatics::SpawnSoundAttached(LoopingSound,GetRootComponent());
}
void ABaseProjectile::Destroyed()
{
	if (LoopingSoundComponent)
	{
		LoopingSoundComponent->Stop(); //停止持续声音
		LoopingSoundComponent->DestroyComponent();//销毁组件
	}
	//清理自动爆炸定时器
	if (GetWorld() && AutoExplodeTimerHandle.IsValid())
	{
		GetWorld()->GetTimerManager().ClearTimer(AutoExplodeTimerHandle);
	}
	//这部分主要是用于客户端判断是否已碰撞
	if (!bHit && !HasAuthority()) OnHit();
	Super::Destroyed();
}

//攻击命中时 触发音效等
void ABaseProjectile::OnHit()
{
	//播放碰撞音效
	UGameplayStatics::PlaySoundAtLocation(this, ImpactSound, GetActorLocation(),FRotator::ZeroRotator);
	//如果有锁定目标 那么爆炸效果就在怪物身上
	if (bOnlyHitSpecificTarget && SpecificTarget)
	{
		UNiagaraFunctionLibrary::SpawnSystemAtLocation(this,ImpactEffect,SpecificTarget->GetActorLocation());
	}
	else
	{
		//在指定位置生成 Niagara 粒子系统特效，如果没锁定目标就是碰到哪里 哪里爆炸
		UNiagaraFunctionLibrary::SpawnSystemAtLocation(this,ImpactEffect,GetActorLocation());
	}
	
	if (LoopingSoundComponent)
	{
		LoopingSoundComponent->Stop(); //停止持续声音
		LoopingSoundComponent->DestroyComponent();//销毁组件
	}
	//防止服务器和客户端在同一个屏幕时，重复多次播放
	bHit = true;
}

//设置自动爆炸定时器
void ABaseProjectile::SetAutoExplodeTimer(float ExplodeTime)
{
	if (GetWorld() && HasAuthority() && ExplodeTime > 0.0f)
	{
		GetWorld()->GetTimerManager().SetTimer(AutoExplodeTimerHandle, this, &ABaseProjectile::AutoExplode, ExplodeTime, false);
	}
}

//设置只碰撞指定目标
void ABaseProjectile::SetOnlyHitSpecificTarget(AActor* SpecificTargetActor)
{
	if (SpecificTargetActor)
	{
		bOnlyHitSpecificTarget = true;
		SpecificTarget = SpecificTargetActor;
	}
}

//自动爆炸函数
void ABaseProjectile::AutoExplode()
{
	if (HasAuthority() && !bHit)
	{
		//触发爆炸效果
		OnHit();
		//销毁投射物
		Destroy();
	}
}
/**
 * 处理球形碰撞组件的重叠事件
 * @param OverlappedComponent  本Actor中触发重叠的碰撞组件（通常是碰撞球）
 * @param OtherActor           与之发生重叠的其他Actor
 * @param OtherComp            与之发生重叠的其他组件
 * @param OtherBodyIndex       与之重叠组件的物理体索引（常用于骨骼网格体，通常为0）
 * @param bFromSweep           是否通过Sweep方式触发（例如移动过程中检测到重叠）
 * @param SweepResult          Sweep检测结果，包括命中位置、法线等详细信息（仅当 bFromSweep 为 true 时有效）
 */
void ABaseProjectile::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
	UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	//判断验证是否允许触发重叠碰撞
	if (!IsValidOverlap(OtherActor)) return;
	//只碰撞指定目标判断
	if (bOnlyHitSpecificTarget && SpecificTarget && OtherActor != SpecificTarget) return;
	
	//防止重复触发
	if (!bHit) OnHit();
	
	if (HasAuthority())
	{
		//计算伤害能力系统 对角色能力系统操作
		if (UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(OtherActor))
		{
			//获取死亡冲力向量
			const FVector DeathImpulse = GetActorForwardVector() * DamageEffectParams.DeathImpulseMagnitude;
			DamageEffectParams.DeathImpulse = DeathImpulse;
			//判断是否触发击退
			const bool bKnockback = FMath::RandRange(1,100) < DamageEffectParams.KnockbackChance;
			if (bKnockback)
			{
				//获取角色的旋转
				FRotator Rotation = GetActorRotation();
				// FRotator Rotation = (OtherActor->GetActorLocation() - SourceAvatarActor->GetActorLocation()).Rotation();
				Rotation.Pitch = 35.f;
				//设置从右向上旋转35度 这样击退可以造成击飞效果GetActorForwardVector().RotateAngleAxis(35.f, GetActorRightVector());
				const FVector KnockbackDirection = Rotation.Vector();
				//获取击退向量
				const FVector KnockbackForce = KnockbackDirection * DamageEffectParams.KnockbackForceMagnitude;
				DamageEffectParams.KnockbackForce = KnockbackForce;
			}
			//这部分是攻击碰到目标的时候，设置施加效果的目标
			DamageEffectParams.TargetAbilitySystemComponent = TargetASC;
			//应用伤害效果参数
			UBaseAbilitySystemLibrary::ApplyDamageEffect(DamageEffectParams);
		}
		//如果是服务器权限，销毁自身
		Destroy();
	}
	else
	{
		//这部分主要是用于客户端判断是否已碰撞
		bHit = true; 
	}
}
//判断验证是否允许触发重叠碰撞
bool ABaseProjectile::IsValidOverlap(AActor* OtherActor)
{
	if (DamageEffectParams.SourceAbilitySystemComponent == nullptr) return false;
	//获取源化身Actor
	AActor* SourceAvatarActor = DamageEffectParams.SourceAbilitySystemComponent->GetAvatarActor();
	//如果重叠的Actor是自身，或者重叠的组件是自身碰撞球，那么就返回 避免攻击自己
	if (SourceAvatarActor == OtherActor) return false;
	//判断如果是盟友 则不造成伤害
	if (!UBaseAbilitySystemLibrary::IsNotFriend( SourceAvatarActor, OtherActor)) return false;

	
	return true;
}


